package com.controller.api;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.biz.*;
import com.controller.agent.BaseController;
import com.core.Result;
import com.core.ResultGenerator;
import com.entity.model.*;
import com.entity.vo.PaymentVO;
import com.sms.SmsUtil;
import com.util.*;
import com.util.Base64;
import com.util.template.Template;
import com.util.template.TemplateParam;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import tk.mybatis.mapper.entity.Condition;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.util.CalendarUtil.getToday;
import static com.util.CalendarUtil.strToDateYmd;

@RestController("apiWxPayController")
@RequestMapping("/api/pay")
public class WeiXinPaymentController {
    @Autowired
    private BillBiz billBiz;

    @Autowired
    private ChangyouVipBiz changyouVipBiz;

    @Autowired
    private CustomerBiz customerBiz;

    @Autowired
    private HotelBiz hotelBiz;

    @Autowired
    private HotelHomeBiz hotelHomeBiz;

    @Autowired
    private HotelReservationBiz hotelReservationBiz;

    private SysConfigBiz sysConfigBiz;

    @Autowired
    private SysBillLogBiz sysBillLogBiz;

    private final String mch_id = "1616009626";//商户号
    private final String spbill_create_ip = "47.99.91.168";//终端IP
    private final String bill_notify_url = "https://dmshotel.51gugua.com/api/pay/billPaycallback";//订单支付通知地址
    private final String trade_type = "JSAPI";//交易类型
    private final String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//统一下单API接口链接
    private final String key = "&key=ladmsdms311323311323311323311323"; // 商户支付密钥
    private final String appid = "wx35a37628e3eb2162";


    /**
     * @param customerId
     * @param body       商品简单描述，该字段请按照规范传递。 例：腾讯充值中心-心悦会员充值
     * @param attach     附加数据，在查询API和支付通知中原样返回，可作为自定义参数使用。 例：广州分店
     * @return
     * @throws UnsupportedEncodingException
     * @throws DocumentException
     */
    @RequestMapping("/billPay")
    public Result billPay(@RequestParam(required = true) Integer customerId, @RequestParam(required = true) Integer billId, @RequestParam(required = false) String body, @RequestParam(required = false) String attach, @RequestParam(required = false) String remark) throws UnsupportedEncodingException, DocumentException {
        try {
            JSONObject JsonObject = new JSONObject();
            //body = new String(body.getBytes("UTF-8"), "ISO-8859-1");
            String nonce_str = UUIDHexGenerator.generate();//随机字符串

            Bill bill = billBiz.findById(billId);
            bill.setRemark(remark);
            billBiz.update(bill);

            Customer customer = customerBiz.findBy("userId", customerId);
            if (customer.getBirthday() != null && !customer.getBirthday().equals("")) {
                Calendar current = Calendar.getInstance();
                Calendar birthDay = Calendar.getInstance();
                birthDay.setTime(strToDateYmd(customer.getBirthday()));
            }

            SysBillLog sysBillLog = new SysBillLog();
            sysBillLog.setBillId(billId);
            sysBillLog.setCustomerId(customerId);
            sysBillLog.setBillLog(JSONArray.toJSON(bill).toString());
            sysBillLog.setTotalFee(0.01);
            sysBillLogBiz.save(sysBillLog);

            String openid = customer.getOpenid();//用户标识
            PaymentVO paymentVO = new PaymentVO();
            paymentVO.setAppid(appid);
            paymentVO.setMch_id(mch_id);
            paymentVO.setNonce_str(nonce_str);
            String newbody = new String(body.getBytes("utf-8"), "iso8859-1");//以utf-8编码放入paymentPo，微信支付要求字符编码统一采用UTF-8字符编码
            paymentVO.setBody(newbody);
            paymentVO.setOut_trade_no(bill.getBillNo());
            DecimalFormat decimalFormat = new DecimalFormat("###################.###########");
            paymentVO.setTotal_fee(decimalFormat.format((0.01 * 100)));
            paymentVO.setSpbill_create_ip(spbill_create_ip);
            paymentVO.setNotify_url(bill_notify_url);
            paymentVO.setTrade_type(trade_type);
            paymentVO.setOpenid(openid);
            // 把请求参数打包成数组
            Map<String, Object> sParaTemp = new HashMap();
            sParaTemp.put("appid", paymentVO.getAppid());
            sParaTemp.put("mch_id", paymentVO.getMch_id());
            sParaTemp.put("nonce_str", paymentVO.getNonce_str());
            sParaTemp.put("body", paymentVO.getBody());
            sParaTemp.put("out_trade_no", paymentVO.getOut_trade_no());
            sParaTemp.put("total_fee", paymentVO.getTotal_fee());
            sParaTemp.put("spbill_create_ip", paymentVO.getSpbill_create_ip());
            sParaTemp.put("notify_url", paymentVO.getNotify_url());
            sParaTemp.put("trade_type", paymentVO.getTrade_type());
            sParaTemp.put("openid", paymentVO.getOpenid());
            // 除去数组中的空值和签名参数
            Map sPara = PayUtil.paraFilter(sParaTemp);
            String prestr = PayUtil.createLinkString(sPara); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串

            //MD5运算生成签名
            String mysign = PayUtil.sign(prestr, key, "utf-8").toUpperCase();
            paymentVO.setSign(mysign);
            //打包要发送的xml
            String respXml = XmlUtil.messageToXML(paymentVO);
            // 打印respXml发现，得到的xml中有“__”不对，应该替换成“_”
            respXml = respXml.replace("__", "_");
            String param = respXml;
            //String result = SendRequestForUrl.sendRequest(url, param);//发起请求
            String result = PayUtil.httpRequest(url, "POST", param);
            System.out.println("请求微信预支付接口，返回 result：" + result);
            // 将解析结果存储在Map中
            Map map = new HashMap();
            InputStream in = new ByteArrayInputStream(result.getBytes());
            // 读取输入流
            SAXReader reader = new SAXReader();
            Document document = reader.read(in);
            // 得到xml根元素
            Element root = document.getRootElement();
            // 得到根元素的所有子节点
            List<Element> elementList = root.elements();
            for (Element element : elementList) {
                map.put(element.getName(), element.getText());
            }
            // 返回信息
            String return_code = map.get("return_code").toString();//返回状态码
            String return_msg = map.get("return_msg").toString();//返回信息
            String result_code = map.get("result_code").toString();//返回状态码

            System.out.println("请求微信预支付接口，返回 code：" + return_code);
            System.out.println("请求微信预支付接口，返回 msg：" + return_msg);
            if ("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)) {
                // 业务结果
                String prepay_id = map.get("prepay_id").toString();//返回的预付单信息
                String nonceStr = UUIDHexGenerator.generate();
                JsonObject.put("appId", appid);
                JsonObject.put("nonceStr", nonceStr);
                JsonObject.put("package", "prepay_id=" + prepay_id);
                Long timeStamp = System.currentTimeMillis() / 1000;
                JsonObject.put("timeStamp", timeStamp + "");
                JsonObject.put("signType", "MD5");
                String stringSignTemp = "appId=" + appid + "&nonceStr=" + nonceStr + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
                //再次签名
                String paySign = PayUtil.sign(stringSignTemp, key, "utf-8").toUpperCase();
                JsonObject.put("paySign", paySign);
            }
            return ResultGenerator.genSuccessResult(JsonObject);
        } catch (Exception e) {
            SysBillLog sysBillLog = sysBillLogBiz.findBy("billId", billId);
            if (sysBillLog != null) {
                sysBillLog.setErrorLog(e.toString());
                sysBillLogBiz.update(sysBillLog);
            } else {
                sysBillLog = new SysBillLog();
                sysBillLog.setCustomerId(customerId);
                sysBillLog.setBillId(billId);
                sysBillLog.setErrorLog(e.toString());
                sysBillLogBiz.save(sysBillLog);
            }
            return ResultGenerator.genFailResult("支付失败");
        }
    }

    /**
     * 预支付时填写的 notify_url ，支付成功后的回调接口
     *
     * @param request
     */
    @PostMapping("/billPaycallback")
    public void billPaycallback(HttpServletRequest request) {
        try {
            Map<String, Object> dataMap = XmlUtil.parseXML(request);
            System.out.print(dataMap);

            Bill bill = billBiz.findBy("billNo", dataMap.get("out_trade_no"));
            if (bill != null) {
                if (bill.getStatus() == 0) {
                    bill.setStatus(1);
                    bill.setPayDate(new Date());
                    bill.setTradeNo(dataMap.get("transaction_id").toString());
                    bill.setCustomerPayFee(Double.valueOf(dataMap.get("total_fee").toString()) / 100);
                    bill.setPayment("wechat");
                    bill.setReceiptFee(Double.valueOf(dataMap.get("total_fee").toString()) / 100);
                    billBiz.update(bill);

                    HotelReservation hotelReservation = hotelReservationBiz.findBy("billId", bill.getId());
                    hotelReservation.setStatus(1);
                    hotelReservationBiz.update(hotelReservation);

                    Hotel hotel = hotelBiz.findById(bill.getHotelId());
                    HotelHome hotelHome = hotelHomeBiz.findById(bill.getHomeId());
                    Customer customer = customerBiz.findById(bill.getCustomerId());

                    SysBillLog sysBillLog = sysBillLogBiz.findBy("billId", bill.getId());
                    sysBillLog.setBillBackLog(JSONArray.toJSON(bill).toString());
                    sysBillLogBiz.update(sysBillLog);

                    /*Template template = new Template();
                    template.setTemplate_id("fISiKy31W4h_HmIsJh3oLh2ib57G2o4N-udVcqfydOw");
                    template.setTouser(customer.getOpenid());
                    template.setPage("pages/index/index");
                    List<TemplateParam> paras = new ArrayList<TemplateParam>();
                    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    paras.add(new TemplateParam("thing1", hotel.getHotelNickName()));
                    paras.add(new TemplateParam("thing8", hotelHome.getHomeName()));
                    paras.add(new TemplateParam("date5", formatter.format(hotelReservation.getReserveStartTime())));
                    paras.add(new TemplateParam("date6", formatter.format(hotelReservation.getReserveEndTime())));
                    paras.add(new TemplateParam("phone_number10", hotel.getHotelTelNo()));
                    template.setTemplateParamList(paras);
                    String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN";
                    requestUrl = requestUrl.replace("ACCESS_TOKEN", getToken());

                    System.out.println(template.toJSON());
                    JSONObject jsonResult = JSON.parseObject(PayUtil.httpRequest(requestUrl, "POST", template.toJSON()));
                    if (jsonResult != null) {
                        System.out.println(jsonResult);
                        String errorCode = jsonResult.getString("errcode");
                        String errorMessage = jsonResult.getString("errmsg");
                        if (errorCode == "0") {
                            System.out.println("Send Success");
                        } else {
                            System.out.println("订阅消息发送失败:" + errorCode + "," + errorMessage);
                        }
                    }*/

                    SmsUtil.sendBillMsg(customer.getAccount(), hotelReservation.getReserveStartTime(), hotelReservation.getReserveEndTime(), hotel.getHotelName(), hotelHome.getHomeName(), hotel.getHotelAddress(), hotel.getHotelTelNo());
                    SmsUtil.sendManageMsg(customer.getAccount(), hotelReservation.getReserveStartTime(), hotelReservation.getReserveEndTime(), hotel.getHotelName(), hotelHome.getHomeName(), hotel.getMobile());
                }
            }
            //{"transaction_id":"4200000109201805293331420304","nonce_str":"402880e963a9764b0163a979a16e0002","bank_type":"CFT","openid":"oXI6G5Jc4D44y2wixgxE3OPwpDVg","sign":"262978D36A3093ACBE4B55707D6EA7B2","fee_type":"CNY","mch_id":"1491307962","cash_fee":"10","out_trade_no":"14913079622018052909183048768217","appid":"wxa177427bc0e60aab","total_fee":"10","trade_type":"JSAPI","result_code":"SUCCESS","time_end":"20180529091834","is_subscribe":"N","return_code":"SUCCESS"}
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String getToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token";
        String result = HttpRequest.sendGet(url, "grant_type=client_credential&appid=wx8a5bf19a3b8d5cd3&secret=52c497db3697593faf66936fd7e3f337");
        JSONObject object = JSON.parseObject(result);
        String Access_Token = object.getString("access_token");
        return Access_Token;
    }
}
